/*****************************************************************************
* File Name: device.h
*
* Version: 1.0
*
* Description:
* This file contains API which integrate all the modules and defines the device 
* functionality in various power modes
*
* Note:
* None
*
* Owner: MRAO
* 
* Related Document:
* None
*
* Hardware Dependency:
* None
*
* Code Tested With:
* 1. PSoC Creator 3.1 
* 2. ARM GCC 4.8.4
******************************************************************************
* Copyright (2015), Cypress Semiconductor Corporation.
******************************************************************************
* This software is owned by Cypress Semiconductor Corporation (Cypress) and is
* protected by and subject to worldwide patent protection (United States and
* foreign), United States copyright laws and international treaty provisions.
* Cypress hereby grants to licensee a personal, non-exclusive, non-transferable
* license to copy, use, modify, create derivative works of, and compile the
* Cypress Source Code and derivative works for the sole purpose of creating
* custom software in support of licensee product to be used only in conjunction
* with a Cypress integrated circuit as specified in the applicable agreement.
* Any reproduction, modification, translation, compilation, or representation of
* this software except as specified above is prohibited without the express
* written permission of Cypress.
*
* Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH
* REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 
* Cypress reserves the right to make changes without further notice to the
* materials described herein. Cypress does not assume any liability arising out
* of the application or use of any product or circuit described herein. Cypress
* does not authorize its products for use as critical components in life-support
* systems where a malfunction or failure may reasonably be expected to result in
* significant injury to the user. The inclusion of Cypress' product in a life-
* support systems application implies that the manufacturer assumes all risk of
* such use and in doing so indemnifies Cypress against all charges. Use may be
* limited by and subject to the applicable Cypress software license agreement.
*****************************************************************************/
#ifndef _DEVICE_H_
#define _DEVICE_H_

#include "platform.h"
#include "stdbool.h"
#include "main.h"
#ifndef DISABLE_MOTION_SENSOR
#include "AIR_MOTION_Lib.h"
#endif /* DISABLE_MOTION_SENSOR */
    
/* Bit position macros */
#define BIT_0_POSITION                           (0u)
#define BIT_1_POSITION                           (1u)
#define BIT_2_POSITION                           (2u)
#define BIT_3_POSITION                           (3u)
#define BIT_4_POSITION                           (4u)
#define BIT_5_POSITION                           (5u)
#define BIT_6_POSITION                           (6u)
#define BIT_7_POSITION                           (7u)
#define BIT_8_POSITION                           (8u)
#define BIT_9_POSITION                           (9u)
#define BIT_10_POSITION                         (10u)
#define BIT_11_POSITION                         (11u)
#define BIT_12_POSITION                         (12u)
#define BIT_13_POSITION                         (13u)
#define BIT_14_POSITION                         (14u)
#define BIT_15_POSITION                         (15u)
#define BIT_16_POSITION                         (16u)
#define BIT_17_POSITION                         (17u)
#define BIT_18_POSITION                         (18u)
#define BIT_19_POSITION                         (19u)
#define BIT_20_POSITION                         (20u)
#define BIT_21_POSITION                         (21u)
#define BIT_22_POSITION                         (22u)
#define BIT_23_POSITION                         (23u)
#define BIT_24_POSITION                         (24u)
#define BIT_25_POSITION                         (25u)
#define BIT_26_POSITION                         (26u)
#define BIT_27_POSITION                         (27u)
#define BIT_28_POSITION                         (28u)
#define BIT_29_POSITION                         (29u)
#define BIT_30_POSITION                         (30u)
#define BIT_31_POSITION                         (31u)

/* Bit mask macros */
#define BIT_0_MASK                              ((uint32)1<<BIT_0_POSITION)
#define BIT_1_MASK                              ((uint32)1<<BIT_1_POSITION)
#define BIT_2_MASK                              ((uint32)1<<BIT_2_POSITION)
#define BIT_3_MASK                              ((uint32)1<<BIT_3_POSITION)
#define BIT_4_MASK                              ((uint32)1<<BIT_4_POSITION)
#define BIT_5_MASK                              ((uint32)1<<BIT_5_POSITION)
#define BIT_6_MASK                              ((uint32)1<<BIT_6_POSITION)
#define BIT_7_MASK                              ((uint32)1<<BIT_7_POSITION)
#define BIT_8_MASK                              ((uint32)1<<BIT_8_POSITION)
#define BIT_9_MASK                              ((uint32)1<<BIT_9_POSITION)
#define BIT_10_MASK                             ((uint32)1<<BIT_10_POSITION)
#define BIT_11_MASK                             ((uint32)1<<BIT_11_POSITION)
#define BIT_12_MASK                             ((uint32)1<<BIT_12_POSITION)
#define BIT_13_MASK                             ((uint32)1<<BIT_13_POSITION)
#define BIT_14_MASK                             ((uint32)1<<BIT_14_POSITION)
#define BIT_15_MASK                             ((uint32)1<<BIT_15_POSITION)
#define BIT_16_MASK                             ((uint32)1<<BIT_16_POSITION)
#define BIT_17_MASK                             ((uint32)1<<BIT_17_POSITION)
#define BIT_18_MASK                             ((uint32)1<<BIT_18_POSITION)
#define BIT_19_MASK                             ((uint32)1<<BIT_19_POSITION)
#define BIT_20_MASK                             ((uint32)1<<BIT_20_POSITION)
#define BIT_21_MASK                             ((uint32)1<<BIT_21_POSITION)
#define BIT_22_MASK                             ((uint32)1<<BIT_22_POSITION)
#define BIT_23_MASK                             ((uint32)1<<BIT_23_POSITION)
#define BIT_24_MASK                             ((uint32)1<<BIT_24_POSITION)
#define BIT_25_MASK                             ((uint32)1<<BIT_25_POSITION)
#define BIT_26_MASK                             ((uint32)1<<BIT_26_POSITION)
#define BIT_27_MASK                             ((uint32)1<<BIT_27_POSITION)
#define BIT_28_MASK                             ((uint32)1<<BIT_28_POSITION)
#define BIT_29_MASK                             ((uint32)1<<BIT_29_POSITION)
#define BIT_30_MASK                             ((uint32)1<<BIT_30_POSITION)
#define BIT_31_MASK                             ((uint32)1<<BIT_31_POSITION)

#define LOGIC_HIGH                              (1)
#define LOGIC_LOW                               (0)

/* Crystal parameters */
#define DEVICE_CRYSTAL_PPM                      CYBLE_LL_SCA_101_TO_150_PPM /* Sleep clock accurary in ppm */
#define DEVICE_ECO_DIVER                        CYBLE_LL_ECO_CLK_DIV_2      /* Link Layer Clock Divider */
#define DEVICE_ECO_START_UP_TIME                25                          /* ECO Crystal start up timer in micosecond */

#define NUMBER_OF_KEYCODES                      (6u)                        /* Number of keycodes that can be sent in 
                                                                             * the report*/
#define AUDIO_BUFFER                            (8)                         /* Number of buffer that can sent in the report */
#define AUDIO_BUFFER_LENGTH                     (20u)                       /* Lenght of the buffer */
#define CONTROL_DATA_LENGTH                     (8)                         /* Length of the control data */

#define LOAD_CAP_VALUE                          (0x8036)                    /* Load cap value for tunning the ECo for 0ppm*/
    
/* Enum for different type of reprort types */
typedef enum _ReportType_
{
    NO_REPORT            = 0x0,
    MOUSE_REPORT         = 0x1,
    KEYBOARD_REPORT      = 0x2,
    MULTIMEDA_REPORT     = 0x4,
    POWER_REPORT         = 0x8,
    BATTERY_REPORT       = 0x10,
    AUDIO_REPORT         = 0x20,
    AUDIO_CONTROL_REPORT = 0x40
}ReportType;

/* Enum for various events that can be raised by the modules */
typedef enum _DeviceEvent_
{
    NO_EVENT        = 0x0,
    KEYBOARD_EVENT  = 0x1,
    BATTERY_EVENT   = 0x2,
    AUDIO_EVENT     = 0x4,
    BUTTON_EVENT    = 0x8,
    BIND_EVENT      = 0x10,
    MOTION_EVENT    = 0x20,
    OPTICAL_EVENT   = 0x40,
    TRACKPAD_EVENT  = 0x80
}DeviceEvent;

/* Structure for sending mouse data */
typedef struct _Mouse_Report_
{
    uint8 click;                            /* Click button status. 
                                             * Oth bit is used for Left click, 
                                             * 1st bit is used for Right Click and 
                                             * 2nd bit is used for middle click 
                                             * 3rd and 4th bit is used for user definedclick */
    int8 x;                                 /* Delta x movement */
    int8 y;                                 /* Delta y movement */
    int8 zwheel;                            /* Delta Vertical movement */
    int8 hwheel;                            /* Delta Horizontal movement */
}Mouse_Report;

/* Structure for sending keyboard data */
typedef struct _Keyboard_Report_
{
    uint8 mkey;                              /* Modifier key */
    uint8 keylength_used;                    /* Number of key used in the key code*/
    uint8 keycode[NUMBER_OF_KEYCODES];       /* key codes */
}Keyboard_Report;

/* Structure for sending system control data */
typedef struct _Power_Report_
{
    uint8 power_key_code;                    /* Power key code */
}Power_Report;

/* Structure for sending multimedia data */
typedef struct _Multimedia_Report_
{
    uint16 multimedia_key_code;              /* Multimedia key code */
}Multimedia_Report;

/* Structure for sending battery data */
typedef struct _Battery_Report_
{    
    uint8 battery;                           /* Battery level in percentage */
}Battery_Report;

/* Structure for sending IR data */
typedef struct _IR_Report_
{
    uint8      isRepeatCode;                 /* IR code to be repeated or not */
    uint8      command;                      /* IR command code */
}IR_Report;

/* Structure for sending audio report */
typedef struct _Audio_Data_
{
    uint8 audio_length;                      /* Length of the Audio packet */
    uint8 audio_buffer[AUDIO_BUFFER_LENGTH]; /* Audio data buffer */
}Audio_Data;

typedef struct _Audio_Control_Packet_
{
    uint8 controlCode;                      /* Control data ID */
    uint8 controlData[CONTROL_DATA_LENGTH]; /* Control information */
    uint8 controlBufferPoint;               /* Positon of the audio packet after which the control information 
                                             * need to be sent */
    uint8 controlDataLength;                /* Length of the control information */
}Audio_Control_Packet;

typedef struct _Audio_Report_
{
    Audio_Data *audio_data[AUDIO_BUFFER]; /* Pointer for collecting the audio packet */
    uint8 noOfAudioPacket;                /* Number of the audio packets to be sent */
}Audio_Report;

/* Structure which encapsulate all the above structure */
typedef struct _Report_
{
    Mouse_Report            mouse_report;         /* Structure for sending mouse report */
    Keyboard_Report         keyboard_report;      /* Structure for sending keyboard report */
    Power_Report            power_report;         /* Structure for sending power report */
    Multimedia_Report       multimedia_report;    /* Structure for sending multimedia report */
    Battery_Report          battery_report;       /* Structure for sending battery report */
    Audio_Report            audio_report;         /* Pointer to structure for sending audio data report */
    Audio_Control_Packet    audio_control_packet; /* Structure for sending audio control report */ 
    IR_Report         ir_report;                  /* Structure for sending IR report */
}Report;

typedef struct _Flash_Data_
{
    uint8 checkSum;
    uint8 version;
#ifndef DISABLE_BLE
    CYBLE_GAP_BD_ADDR_T blePeerAddress;
#endif /* DISABLE_BLE */
#ifndef DISABLE_MOTION_SENSOR
    t_struct_AIR_MOTION_SensorAxis motionGyroOffest;
#endif /* DISABLE_MOTION_SENSOR */
}Flash_Data;

extern bool writeFlashData;
extern Flash_Data flashDataInRam;

/* Macro for reading and raising the event from the modules */
#define DEVICE_POST_EVENT(evt)                 { deviceEvent |= evt; }
#define DEVICE_GET_EVENT(evt)                  ( deviceEvent & evt   )

/* Macro for indicating any activity  from the modules in low power state */
#define DEVICE_ACTIVITY_DETECTED()             (isActitiyDetected = true)
/* Macro for reading and raising the activity detection from the modules */
#define DEVICE_LOW_BATTERY_DETECTED()          (isBatteryLow = true)

/* Macro for copying data into ram before writing into the flash */
#define Device_Flash_Write(dest,src,size)      { memcpy(dest, src, size); writeFlashData = true; }
#define Device_Flash_Restore(dest,src,size)    memcpy(dest, src, size)

/* Various time out values for the various power modes */
#define DEVICE_ACTIVE_TIMEOUT                    (3000u)
#define DEVICE_IDLE_TIMEOUT                      (10000u)
#ifndef ENABLE_SYSTEM_DEEP_SLEEP
#define DEVICE_SLEEP_TIMEOUT                     (4294967295u)
#else
#define DEVICE_SLEEP_TIMEOUT                     (500000u)
#endif /* ENABLE_SYSTEM_DEEP_SLEEP */
#define DEVICE_DEEP_SLEEP_TIMEOUT                (4294967295u)

/* Battery Monitoring Macros */
#define DEVICE_INITIAL_BATTERY_LEVEL             (100u)
#define DEVICE_NO_BATTERY_MINIPROG_CONNECTED     (0x300)
                                                                       /* Applied Values */   /* Other Values for references */
#define DEVICE_BATTERY_CUT_OFF_VOLTAGE           (1220u)   /* Assuming  1.8V cutoff (0x4C4)   | 2.0V Cuff Off(0x54C) */
#define DEVICE_BATTERY_LOW_VOLTAGE               (1359u)   /* Assuming  2.0V  (0x54F)         | 2.1V Low Battery (0x590) */
#define DEVICE_BATTERY_MAX_VOLTAGE               (2003u)   /* Assuming  3.0V Max Battery (0x7D3) */
#define DEVICE_BATTERY_SCAN_TIME_MS              (3000u)   /* Interval as which the battery need to be scanned */

#ifndef DEVICE_BATTERY_PARALLEL
#define DEVICE_BATTERY_THRESHOLD                 (5u)
#endif /* DEVICE_BATTERY_PARALLEL */

#define BATTERY_MONITORING_ABOVE_VOLTAGE         (0x0)
#define BATTERY_MONITORING_LOW_VOLTAGE           (0x1)
#define BATTERY_MONITORING_CUT_OFF_VOLTAGE       (0x2)

#define TIME_BETWEEN_TWO_POLL_ACTIVE             (10u)
#define TIME_BETWEEN_TWO_POLL_IDLE               (125u)
#define TIME_BETWEEN_TWO_POLL_SLEEP              (250u)
#define TIME_BETWEEN_TWO_POLL_DEEP_SLEEP         (500u)


/* Slow Breathing Led Timing 
* <------REPEAT----------->
*     _________
*    /         \
*   /           \
*  /             \
* /               \____________
* <rT> <--ST--><-fT><---lT---->
*/
/* Breathing Led Times in msec */
/* Slow Breathing Led timing */
#define DEVICE_LED_SLOW_RISE_TIME               (1248u)
#define DEVICE_LED_SLOW_HIGH_STANDBY_TIME       (250u)
#define DEVICE_LED_SLOW_FALL_TIME               (624u)
#define DEVICE_LED_SLOW_LOW_STANDBY_TIME        (0050u)
#define DEVICE_LED_ADVERT_SLOW_LOW_STANDBY_TIME (250u)
#define DEVICE_LED_SLOW_REPEAT_COUNT               (0u)
#define DEVICE_LED_ADVERT_SLOW_REPEAT_COUNT        (10u)

/* Fast Breathing Led Timing */
#define DEVICE_LED_FAST_RISE_TIME                (156u)
#define DEVICE_LED_FAST_HIGH_STANDBY_TIME         (25u)
#define DEVICE_LED_FAST_FALL_TIME                (156u)
#define DEVICE_LED_FAST_LOW_STANDBY_TIME         (050u)
#define DEVICE_LED_FAST_REPEAT_COUNT               (0u)

/* Connected breathing Led Timing */
#define DEVICE_LED_CONNECTED_RISE_TIME           (156u)
#define DEVICE_LED_CONNECTED_HIGH_STANDBY_TIME    (25u)
#define DEVICE_LED_CONNECTED_FALL_TIME           (156u)
#define DEVICE_LED_CONNECTED_LOW_STANDBY_TIME    (050u)
#define DEVICE_LED_CONNECTED_REPEAT_COUNT          (3u)

/* Led On Intensity */
#define DEVICE_LED_ON_INTENSITY                   (4000u)
#define DEVICE_LEX_MAX_INTENSITY                  (4000u)

/* Threshold in number of times the directed ADV need to be performed before shifting to Undirected ADV */
#define DEVICE_DIRECTED_ADV_THRESHOLD             (0u) 
/* Note: Setting the DEVICE_DIRECTED_ADV_THRESHOLD threshold to zero will disable directed adv and does only 
 * undirected with whitelist filtering. */

/* Threshold in number of times the Undirected ADV need to be performed before shifting to Directed ADV */
#define DEVICE_UNDIRECTED_ADV_THRESHOLD           (1u)

#if (DEVICE_DIRECTED_ADV_THRESHOLD == 0) && (DEVICE_UNDIRECTED_ADV_THRESHOLD == 0)
    #error "Both DEVICE_DIRECTED_ADV_THRESHOLD and DEVICE_UNDIRECTED_ADV_THRESHOLD macro cannot be set to zero"
#endif /*(DEVICE_DIRECTED_ADV_THRESHOLD == 0) && (DEVICE_UNDIRECTED_ADV_THRESHOLD == 0) */

#define Device_GetCurrent_State()                 (deviceState)
/* Macros that define the led behaviour for the device */
#define Device_DeepSleep()                        Device_Low_Power_State(DEVICE_DEEP_SLEEP,DEVICE_DEEP_SLEEP_TIMEOUT, TIME_BETWEEN_TWO_POLL_DEEP_SLEEP)
#define Device_Sleep()                            Device_Low_Power_State(DEVICE_SLEEP,DEVICE_SLEEP_TIMEOUT, TIME_BETWEEN_TWO_POLL_SLEEP)
#define Device_Idle()                             Device_Low_Power_State(DEVICE_IDLE,DEVICE_IDLE_TIMEOUT, TIME_BETWEEN_TWO_POLL_IDLE)

#define Device_Led_Fast_Blinking()                Timer_CallBack_Enable();\
                                                  Led_Blinking(DEVICE_LED_FAST_RISE_TIME, \
                                                         DEVICE_LED_FAST_HIGH_STANDBY_TIME, \
                                                         DEVICE_LED_FAST_FALL_TIME, \
                                                         DEVICE_LED_FAST_LOW_STANDBY_TIME,\
                                                         DEVICE_LED_FAST_REPEAT_COUNT)

#define Device_Led_Slow_Blinking()                Timer_CallBack_Enable();\
                                                  Led_Blinking(DEVICE_LED_SLOW_RISE_TIME, \
                                                         DEVICE_LED_SLOW_HIGH_STANDBY_TIME, \
                                                         DEVICE_LED_SLOW_FALL_TIME, \
                                                         DEVICE_LED_SLOW_LOW_STANDBY_TIME,\
                                                         DEVICE_LED_SLOW_REPEAT_COUNT)

#define Device_Led_Connected()                    Timer_CallBack_Enable();\
                                                  Led_Blinking(DEVICE_LED_CONNECTED_RISE_TIME, \
                                                         DEVICE_LED_CONNECTED_HIGH_STANDBY_TIME, \
                                                         DEVICE_LED_CONNECTED_FALL_TIME, \
                                                         DEVICE_LED_CONNECTED_LOW_STANDBY_TIME,\
                                                         DEVICE_LED_CONNECTED_REPEAT_COUNT)

#define Device_Led_On_Continous()           			Led_On(DEVICE_LED_ON_INTENSITY)

#define Device_Led_Adverting()           					Timer_CallBack_Enable();\
                                            			Led_Blinking(DEVICE_LED_SLOW_RISE_TIME, \
                                                         DEVICE_LED_SLOW_HIGH_STANDBY_TIME, \
                                                         DEVICE_LED_SLOW_FALL_TIME, \
                                                         DEVICE_LED_ADVERT_SLOW_LOW_STANDBY_TIME,\
                                                         DEVICE_LED_ADVERT_SLOW_REPEAT_COUNT)
#define Device_Led_Fast_LightOnece()                Timer_CallBack_Enable();\
																										Led_Blinking(DEVICE_LED_FAST_RISE_TIME, \
																													 DEVICE_LED_FAST_HIGH_STANDBY_TIME, \
																													 DEVICE_LED_FAST_FALL_TIME, \
																													 DEVICE_LED_FAST_LOW_STANDBY_TIME,\
																													 DEVICE_LED_FAST_REPEAT_ONECE)

#define Device_Led_BlinkComplete()                Led_IsComplete()
#define Device_Led_Stop()                         Timer_CallBack_Disable();\
                                                  Led_Stop();

/* Device IR Address */
#define Device_IR_Address                         (0x0707)

extern DeviceEvent deviceEvent;
extern uint8 isActitiyDetected;
extern uint8 isBatteryLow;

/* current power state of the device */
extern Device_State deviceState;

/*****************************************************************************
* Function Name: Device_Init()
******************************************************************************
* Summary:
* This function initializes various modules
*
* Parameters:
* None
*
* Return:
*
* None
*
*****************************************************************************/
extern void Device_Init(void);

/*****************************************************************************
* Function Name: Device_Timer_CallBack()
******************************************************************************
* Summary:
* This function is called when a timer interrupt occurs. This function can 
* be used to update any parameter with the tick of timer. Currently it is used 
* to update the Led Module to provide the Breathing Led effect
*
* Parameters:
* None
*
* Return:
* None
*
*****************************************************************************/
extern void Device_Timer_Callback(void);

/*****************************************************************************
* Function Name: Device_ShutDown()
******************************************************************************
* Summary:
* This function defines the behaviour for the device in stop state (DEVICE_STOP)
*
* Parameters:
* None
*
* Return:
* None
*
*****************************************************************************/
extern void Device_ShutDown(void);

/*****************************************************************************
* Function Name: Device_Active()
******************************************************************************
* Summary:
* This function defines the behaviour for the device in active state(DEVICE_ACTIVE)
*
* Parameters:
* None
*
* Return:
* None
*
*****************************************************************************/
extern void Device_Active(void);

/*****************************************************************************
* Function Name: Device_Low_Power_State()
******************************************************************************
* Summary:
* This function defines the behaviour for the device in low power state(DEVICE_IDLE, 
* DEVICE_SLEEP and DEVICE_DEEPSLEEP state)
*
* Parameters:
* Device_State state - current device state 
* uint32 timeOut - Time out that it is required to be in that state
* uint32 timeBetweenTwoPoll - Time between two polls
*
* Return:
* None
*
*****************************************************************************/
extern void Device_Low_Power_State(Device_State state, uint32 lowPowerTimeOut, uint32 timeBetweenTwoPoll);

#endif /* _DEVICE_H_ */
